java 数值包装类原理剖析

前言

在JDK1.5以上版本中,提供了基本数据类型的自动装箱及拆箱功能(装箱:将基本数据类型自动转为包装类对象;拆箱:将包装类对象自动转为基本数据类型)。

原理剖析

分析以下demo的运行结果:

/** Integer案例**/  
Integer i1 = 128;
Integer i2 = 128;
Integer i3 = 127;
Integer i4 = 127;
System.out.println(i1 == i2);//false
System.out.println(i3==i4); //true

/** Long案例**/
Long l1 = 128L;
Long l2 = 128L;
Long l3 = -128L;
Long l4 = -128L;
System.out.println(l1 == l2);//false
System.out.println(l3==l4);//true

/**Float(Double)案例(形成对比)**/
Float f1 = 128f;
Float f2 = 128f;
Float f3 = 127f;
Float f4 = 127f;
System.out.println(f1 == f2);//false
System.out.println(f3==f4);//false

首先 Integer i1 = 127;将基本数据类型赋给包装类,会调用Integer.valueOf(int i)自动装箱,转换为包装类对象。同理,将包装类对象赋给基本数据类型,会调用intValue()方法自动拆箱。如果该包装类对象为null,则会出现NullPointerException异常。之所以会出现上述结果。因为Byte,Integer,Long对在-128~127之间的数据进行了缓存,如果待转换的数值 i 在该范围了则直接从缓存取,而不是new Integer(i)。
而Float和Double则是每次都new一个新的,没有缓存机制,所以都为false。

JDK自动装箱源码如下:

/**Integer的实现**/  
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
//IntegerCache.high为127,取缓存
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}

/**Long的实现**/
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}

/**Float的实现(无缓存)**/
public static Float valueOf(float f) {
return new Float(f);
}

总结

Integer i = 127; //jvm调用Integer.valueOf(int v);自动装箱
int n = i; //jvm 会调用Integer.intValue();自动拆箱